home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
umddvi
/
dev
/
dmdslave.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-01
|
21KB
|
1,177 lines
/*
* Typesetter/Terminal Emulator for the DMD 5620
*
* Lou Salkind
* New York University
* Thu Apr 2 01:21:09 EST 1987
*
* This program was inspired by the DMD proof program
* and the Impress typesetting language. It is used by
* the TeX DVIDMD driver.
*/
#include <jerq.h>
#include "layer.h"
#include "font.h"
#include "dmdcodes.h"
#define MAXFAMILY 128 /* number of different fonts */
#define MAXFONTNAME 16 /* maximum font string */
#define PAGECHAR 8192 /* buffered characters to save */
#define MAXPAGE 127
#define SCROLLSIZE 20 /* scrolling border */
#define PAGEPIXELS 1010 /* XXX - length of page (should be an argument) */
#define NEWLINESIZE 16
#define CURSOR '\01' /* cursor char in font */
#define LINEBUFSIZE 100
#define MOVED 256
#ifdef PAGECHAR
/* treatment of input characters */
#define CHAR_DISCARD 0
#define CHAR_STORE 1
#define CHAR_FETCH 2
int savechars;
char savebuf[PAGECHAR];
char *saveptr;
#endif
#define RoundUp(a, b) (((a) + (b) - 1) & ~((b) - 1))
#ifdef MPX
#undef cursinhibit
#undef cursallow
#define cursinhibit() {}
#define cursallow() {}
#endif
static Texture16 prompt = {
0x0000, 0x0000, 0x0000, 0x322E, 0x4B69, 0x4369, 0x42A9, 0x42A9,
0x42A9, 0x4229, 0x4229, 0x4229, 0x322E, 0x0000, 0x0000, 0x0000
};
Point fudge = {5, 3}; /* DAG - offsets from corners */
int dotypeset; /* 1==typesetter, 0==terminal */
int cursvis; /* is cursor visible */
Point org; /* current origin */
Point typeorg; /* current typesetter origin */
Point curpt; /* current typesetter point relative to origin */
Point curpos; /* current ascii terminal position */
struct line {
char buf[LINEBUFSIZE];
char *bufp;
};
struct line line;
struct glyph {
Bitmap g_bitmap;
short g_pxwidth;
short g_xoffset;
short g_yoffset;
};
struct fontinfo {
char f_name[MAXFONTNAME];
struct glyph f_glyph[128];
};
struct fontinfo *ftbl[MAXFAMILY];
struct fontinfo *curfont;
Point inpoint();
main()
{
register int c;
resetmode(DMD_TERM);
#ifdef MPX
P->state |= RESHAPED; /* set window parameters */
#else
Drect = inset(Drect, 2);
#endif /* MPX */
windowupdate();
for(;;) {
c = inchar();
if (dotypeset)
typeset(c);
else {
if(cursvis)
term(CURSOR, 0); /* undraw cursor */
term(c, 1);
while (own()&RCV)
term(inchar(), 1);
term(CURSOR, 0); /* draw at new spot */
cursvis = 1;
}
}
}
/* terminal emulation */
term(c, advance)
register int c;
{
register struct line *linep = &line;
register Point *pp = &curpos;
register Fontchar *fp;
Rectangle r;
Point p;
if (c & 0x80) {
if (c == DMD_TYPESET) {
resetmode(DMD_TYPESET);
send(DMD_ACK);
return;
}
c &= 0x7F;
}
switch(c) {
default:
fp = defont.info+c;
if (fp->width+pp->x >= Drect.corner.x)
newline(linep, pp);
p = *pp;
r.origin.x = fp->x;
r.corner.x = (fp+1)->x;
if (advance) {
r.origin.y = 0;
r.corner.y = defont.height;
bitblt(defont.bits, r, &display, p, F_STORE);
pp->x += fp->width;
if (linep->bufp < linep->buf+LINEBUFSIZE)
*linep->bufp++ = c;
} else {
r.origin.y = fp->top;
r.corner.y = fp->bottom;
p.y += fp->top;
bitblt(defont.bits, r, &display, p, F_XOR);
}
break;
case '\n':
newline(linep, pp);
break;
case '\7':
ringbell(); /* DAG -- should work? */
case 0:
break;
case '\r':
pp->x=Drect.origin.x+fudge.x; /* DAG -- changed 5 to fudge.x */
linep->bufp = linep->buf;
break;
case '\013': /* ^K: reverse linefeed */
if(pp->y>Drect.origin.y+fudge.y+defont.height)
pp->y-=NEWLINESIZE;
break;
case '\b':
backspace(linep, pp);
break;
case '\014':
formfeed(linep, pp);
break;
case '\t':
pp->x=nexttab(pp->x);
if(pp->x>=Drect.corner.x)
newline(linep, pp);
if(linep->bufp<linep->buf+LINEBUFSIZE)
*linep->bufp++=c;
break;
}
}
/*int eightspaces=8*dispatch[' '].c_wid;*/
int eightspaces=72;
nexttab(x)
{
register int xx = x-Drect.origin.x-fudge.x;
return(xx-(xx%eightspaces)+eightspaces+Drect.origin.x+fudge.x);
}
backspace(linep, pp)
register struct line *linep;
register Point *pp;
{
register char *p;
register int x = Drect.origin.x+fudge.x;
if (linep->bufp>linep->buf) {
for (p=linep->buf; p<linep->bufp-1; p++)
if (*p=='\t')
x = nexttab(x);
else
x += defont.info[*p].width;
pp->x = x;
--linep->bufp;
if (*p!='\t')
term(*p, 0);
}
}
newline(linep, pp)
struct line *linep;
register Point *pp;
{
register cursoff=0;
if (pp->y+2*NEWLINESIZE > Drect.corner.y-fudge.y+1) {
/* weirdness is because the tail of the arrow may be anywhere */
if (rectXrect(Rect(mouse.xy.x-16, mouse.xy.y-16, mouse.xy.x+16,
mouse.xy.y+16), Drect)){
cursinhibit();
cursoff++;
}
lscroll();
if(cursoff)
cursallow();
} else
pp->y += NEWLINESIZE;
pp->x = Drect.origin.x+fudge.x;
linep->bufp = linep->buf;
}
lscroll()
{
Rectangle r;
r = Drect;
r.origin.y += NEWLINESIZE;
bitblt(&display, r, &display, Pt(r.origin.x, r.origin.y-NEWLINESIZE), F_STORE);
stipple(Rpt(Pt(Drect.origin.x, Drect.corner.y-NEWLINESIZE), Drect.corner));
}
formfeed(linep, pp)
struct line *linep;
Point *pp;
{
cursinhibit();
stipple(Drect);
cursallow();
*pp=add(Drect.origin, fudge);
linep->bufp=linep->buf;
}
stipple(r)
Rectangle r;
{
cursinhibit();
rectf(&display, r, F_CLR);
cursallow();
}
/* routines to handle command input */
inchar()
{
register int c;
#ifdef PAGECHAR
if (savechars == CHAR_FETCH)
return(*saveptr++ & 0377);
#endif
#ifdef MPX
wait(RCV);
if (P->state&(RESHAPED|MOVED))
windowupdate();
c = rcvchar();
#else
for ( ; ; ) {
wait(RCV|KBD);
if (own() & RCV) {
c = rcvchar();
break;
}
if (!dotypeset)
send(kbdchar());
}
#endif MPX
#ifdef PAGECHAR
if (savechars == CHAR_STORE) {
if (saveptr < &savebuf[PAGECHAR])
*saveptr++ = c;
else
savechars = CHAR_DISCARD;
}
#endif
return(c&0377);
}
insignchar()
{
register int c;
c = inchar();
if (c > 127)
c -= 256;
return(c);
}
inshort()
{
register short i;
i = inchar() << 8;
i |= inchar();
return(i);
}
Point
inpoint()
{
Point p;
p.x = inshort() + typeorg.x;
p.y = inshort() + typeorg.y;
return(p);
}
send(c)
{
char cc = c;
sendnchars(1, &cc);
}
/* typesetter emulation */
typeset(c)
register int c;
{
register struct glyph *g;
register Bitmap *b;
Point pprime;
int old;
if (c <= 127) {
if (curfont == 0)
return;
g = &curfont->f_glyph[c];
b = &g->g_bitmap;
if (b->base == 0) {
curpt.x += g->g_pxwidth;
return;
}
pprime = add(curpt, typeorg);
pprime.x -= g->g_xoffset;
pprime.y -= g->g_yoffset;
bitblt(b, b->rect, &display, pprime, F_OR);
curpt.x += g->g_pxwidth;
return;
}
switch (c) {
case DMD_EXIT:
bye();
break;
case DMD_TERM:
#ifdef PAGECHAR
savechars = CHAR_DISCARD;
#endif
resetmode(DMD_TERM);
break;
case DMD_CLEAR:
stipple(Drect);
curpos = add(org, fudge);
break;
case DMD_TYPESET:
send(DMD_ACK);
break;
case DMD_ASCII:
#ifdef PAGECHAR
if (savechars == CHAR_STORE)
saveptr--;
old = savechars;
savechars = CHAR_DISCARD;
#endif
while (c = inchar())
term(c, 1);
#ifdef PAGECHAR
savechars = old;
#endif
break;
case DMD_RULE: {
short w, h;
Rectangle r;
w = inshort();
h = inshort();
pprime = add(curpt, typeorg);
pprime.y++;
r.origin = pprime;
r.origin.y = pprime.y - h;
r.corner = pprime;
r.corner.x = pprime.x + w;
rectf(&display, r, F_STORE);
break;
}
case DMD_FORW:
curpt.x++;
break;
case DMD_BACK:
curpt.x--;
break;
case DMD_HABS:
curpt.x = inshort();
break;
case DMD_HREL:
curpt.x += insignchar();
break;
case DMD_VABS:
curpt.y = inshort();
break;
case DMD_VREL:
curpt.y += insignchar();
break;
case DMD_PAGE:
#ifdef PAGECHAR
saveptr = savebuf;
savechars = CHAR_STORE;
#endif
stipple(Drect);
curpos = add(org, fudge);
curpt.x = curpt.y = 0;
break;
case DMD_ENDPAGE:
pagecmd();
break;
case DMD_SETFONT: {
int i;
i = inchar();
if (i < MAXFAMILY)
curfont = ftbl[i];
break;
}
case DMD_MKFONT:
case DMD_SGLYPH:
case DMD_BGLYPH:
#ifdef PAGECHAR
if (savechars == CHAR_STORE)
saveptr--;
old = savechars;
savechars = CHAR_DISCARD;
#endif
if (c == DMD_MKFONT)
ldfont();
else
ldglyph(c);
#ifdef PAGECHAR
savechars = old;
#endif
break;
case DMD_SEGMENT:
case DMD_SPLINE:
define_path(c);
break;
case DMD_CIRCLE:
define_circle();
break;
case DMD_ELLIPSE:
define_ellipse();
break;
case DMD_DRAWPATH:
draw_path();
break;
case DMD_FILLPATH:
fill_path();
break;
case DMD_PENSIZE:
set_pen();
break;
default:
break;
}
}
/* request an index number for a new font */
ldfont()
{
register struct fontinfo *f;
register int i, j;
register int x = -1;
char name[MAXFONTNAME];
register char *p;
char loaded[16];
p = name;
while (*p++ = inchar())
if (p >= &name[MAXFONTNAME]) {
while (inchar())
continue;
break;
}
for (i = 0; i < sizeof(loaded); i++)
loaded[i] = 0;
/* look for the font... */
for (i = 0; i < MAXFAMILY; i++) {
f = ftbl[i];
if (f && strncmp(f->f_name, name, sizeof(f->f_name)) == 0) {
for (j = 0; j < 128; j++) {
if (f->f_glyph[j].g_bitmap.base)
loaded[j>>3] |= 1 << (~j & 07);
}
send(i);
sendnchars(sizeof(loaded), loaded);
return;
}
if (x == -1 && f == 0)
x = i;
}
if (x == -1) {
send(-1);
return;
}
f = (struct fontinfo *)alloc(sizeof (struct fontinfo));
if (f == 0) {
send(-1);
return;
}
ftbl[x] = f;
strncpy(f->f_name, name, sizeof(f->f_name));
send(x);
sendnchars(sizeof(loaded), loaded);
}
/* download a particular character in a font */
ldglyph(c)
int c;
{
register struct glyph *g;
register int i, j;
register char *p;
short chr, fam, w;
int words;
int o;
short xs, ys;
int endb;
static struct glyph gdummy;
w = inshort();
fam = (w >> 7) & 0177;
chr = w & 0177;
if (ftbl[fam])
g = &(ftbl[fam]->f_glyph[chr]);
else {
ftbl[fam] = (struct fontinfo *)alloc(sizeof (struct fontinfo));
g = ftbl[fam] ? &(ftbl[fam]->f_glyph[chr]) : &gdummy;
}
if (c == DMD_SGLYPH) {
g->g_pxwidth = insignchar();
xs = inchar();
g->g_xoffset = insignchar();
ys = inchar();
g->g_yoffset = insignchar();
} else {
g->g_pxwidth = inshort();
xs = inshort();
g->g_xoffset = inshort();
ys = inshort();
g->g_yoffset = inshort();
}
words = RoundUp(xs, WORDSIZE) >> WORDSHIFT;
o = RoundUp(xs, 8) >> 3;
endb = words * sizeof(Word);
if (g->g_bitmap.base)
free(g->g_bitmap.base);
if (g == &gdummy || (p = alloc(ys * endb)) == 0) {
/* skip raster bytes */
j = o * ys;
for (i = 0; i < j; i++)
inchar();
} else {
/* read raster here */
g->g_bitmap.base = (Word *)p;
g->g_bitmap.width = words;
g->g_bitmap.rect.origin.x = 0;
g->g_bitmap.rect.origin.y = 0;
g->g_bitmap.rect.corner.x = xs;
g->g_bitmap.rect.corner.y = ys;
g->g_bitmap._null = 0;
p = (char *)g->g_bitmap.base;
for (j = 0; j < ys; j++) {
for (i = 0; i < o; i++)
*p++ = inchar();
for ( ; i < endb; i++)
*p++ = 0;
}
}
}
/* mouse and keyboard input routines at end of page */
static char *b3m[] = {
"redraw",
"next",
"prev",
"quit",
"exit",
NULL
};
static Menu menu = { b3m };
Texture16 ok = {
0x1C44, 0x2248, 0x2250, 0x2270,
0x2248, 0x1C44, 0x0000, 0x0380,
0x0440, 0x0440, 0x0080, 0x0100,
0x0100, 0x0100, 0x0000, 0x0100,
};
minkbd()
{
Texture16 *t;
register int i;
int oscroll = 0;
register int inscroll = 0;
Point selpt;
while (i = wait(KBD|MOUSE|RCV)) {
if (i&KBD)
return(kbdchar());
else if (i&RCV)
return(rcvchar());
selpt = mouse.xy;
i = selpt.x - Drect.origin.x;
inscroll = 0;
if (i >= 0 && i < SCROLLSIZE)
inscroll += 1;
i = Drect.corner.y - selpt.y;
if (i >= 0 && i < SCROLLSIZE)
inscroll += 2;
if (inscroll != oscroll) {
cursswitch(inscroll ? &C_crosshair : &prompt);
oscroll = inscroll;
}
switch (inscroll) {
case 0:
if (!bttn3())
break;
switch (i = menuhit(&menu, 3)) {
case -1:
break;
case 4:
t = cursswitch(&ok);
while (!bttn123()) sleep(1);
i = bttn3();
while (bttn123()) sleep(1);
(void)cursswitch(t);
if (i)
return('x');
break;
default:
return("rnpq"[i]);
}
break;
case 1:
if (!bttn13())
break;
if (bttn1())
typeorg.y -= selpt.y - Drect.origin.y;
else
typeorg.y += selpt.y - Drect.origin.y;
/* primitive scroll for now */
while (bttn123());
return('s');
case 2:
if (!bttn13())
break;
if (bttn1())
typeorg.x -= selpt.x - Drect.origin.x;
else
typeorg.x += selpt.x - Drect.origin.x;
/* primitive scroll for now */
while (bttn123());
return('s');
case 3:
if (bttn1())
return('n');
else if (bttn2())
return('r');
else if (bttn3())
return('p');
break;
}
sleep(1);
}
/*NOT REACHED*/
}
pagecmd()
{
register int i;
register Texture16 *t;
int cmd;
Point p1, p2;
int redraw;
#ifdef PAGECHAR
int pagesaved;
char buf[40];
pagesaved = savechars != CHAR_DISCARD;
#endif
t = cursswitch(&prompt);
pgstart:
redraw = 0;
/*
* draw outlines of scroll bars. We will draw
* the whole lines when we can't write in the
* scroll area, but for now, do it this way.
*/
p1 = Drect.origin;
p1.x += SCROLLSIZE;
p2.x = p1.x;
p2.y = p1.y + SCROLLSIZE;
segment(&display, p1, p2, F_STORE);
p1.y = Drect.corner.y - 2*SCROLLSIZE;
p2.y = Drect.corner.y;
segment(&display, p1, p2, F_STORE);
p1.y = Drect.corner.y - SCROLLSIZE;
p2.y = p1.y;
p1.x = Drect.origin.x;
p2.x = p1.x + 2*SCROLLSIZE;
segment(&display, p1, p2, F_STORE);
p1.x = Drect.corner.x - SCROLLSIZE;
p2.x = Drect.corner.x;
segment(&display, p1, p2, F_STORE);
#ifdef PAGECHAR
savechars = CHAR_DISCARD;
#ifdef DEBUG
sprintf(buf, "%d", saveptr-savebuf);
p1 = org;
p1.x += 20;
p1.y += 20;
string(&defont, buf, &display, p1, F_XOR);
#endif
#endif
switch (cmd = minkbd()) {
case 0177:
case 04:
case 'q':
send(DMD_EXIT);
resetmode(DMD_TERM);
t = 0;
break;
case 'x':
send(DMD_EXIT);
bye();
break;
case 'r':
case '\f':
typeorg = org;
/* fall into... */
case 's':
redraw = 1;
break;
case 'n':
case ' ':
typeorg.y -= Drect.corner.y - Drect.origin.y;
if (org.y - typeorg.y < PAGEPIXELS) {
redraw = 1;
break;
}
/* fall into... */
case '+':
case '\r':
case '\n':
typeorg = org;
send(DMD_PAGE);
send(1);
break;
case 'p':
typeorg.y += Drect.corner.y - Drect.origin.y;
if (org.y >= typeorg.y) {
redraw = 1;
break;
}
/* fall into... */
case '-':
typeorg = org;
send(DMD_PAGE);
send(-1);
break;
default:
/* ringbell(); */
goto pgstart;
}
if (redraw) {
#ifdef PAGECHAR
if (pagesaved) {
#ifdef MPX
if (P->state&(RESHAPED|MOVED))
windowupdate();
#endif
typeset(DMD_PAGE);
saveptr = savebuf;
savechars = CHAR_FETCH;
while ((i = inchar()) != DMD_ENDPAGE)
typeset(i);
(void)cursswitch(&prompt);
goto pgstart;
}
#endif
send(DMD_PAGE);
send(0);
}
(void)cursswitch(t);
}
inkbd()
{
wait(RCV|KBD);
return((own()&KBD)? kbdchar():rcvchar());
}
bye()
{
register int i;
for (i = 0; i < MAXFAMILY; i++) {
if (ftbl[i])
freefont(ftbl[i]);
}
exit();
}
freefont(f)
struct fontinfo *f;
{
struct glyph *g;
for (g = f->f_glyph; g < &f->f_glyph[128]; g++)
if (g->g_bitmap.base)
free((char *)g->g_bitmap.base);
free((char *)f);
}
#ifdef notdef
edit(s)
char *s;
{
char buf[40];
Point p;
int c;
register i;
strcpy(buf, s);
p = mouse.xy;
disp(buf, p);
for(i = strlen(buf); (c = inkbd()) != '\r';)
{
disp(buf, p);
p = mouse.xy;
switch(c)
{
case '\b':
if((buf[i] != ' ') && (i > 0))
buf[--i] = 0;
break;
case '@':
while(buf[i] != ' ') i--;
buf[++i] = 0;
break;
default:
buf[i++] = c;
buf[i] = 0;
break;
}
disp(buf, p);
}
disp(buf, p);
strcpy(s, buf);
}
disp(s, p)
char *s;
Point p;
{
string(&defont, "\001", &display,
string(&defont, s, &display, p, F_XOR), F_XOR);
}
#endif
resetmode(c)
int c;
{
if (c == DMD_TERM) {
cursvis = dotypeset = 0;
#ifdef MPX
request(SEND|RCV);
#else
request(SEND|RCV|KBD);
#endif
curpos.x = org.x + fudge.x;
curpos.y = Drect.corner.y - fudge.y - defont.height;
} else {
dotypeset = 1;
request(SEND|RCV|KBD|MOUSE);
typeorg = org;
}
}
windowupdate()
{
#ifdef MPX
if (P->state&RESHAPED) {
#endif
org = Drect.origin;
typeorg = org;
curpos = add(org, fudge);
line.bufp = line.buf;
if (cursvis) {
term(CURSOR, 0); /* flip state */
cursvis = 0;
}
#ifdef MPX
} else {
curpos = add(sub(curpos, org), Drect.origin);
typeorg = add(sub(typeorg, org), Drect.origin);
org = Drect.origin;
}
P->state &= ~(MOVED|RESHAPED);
#endif
artdeco();
}
static Texture16 vstripe = {
0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0,
0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0,
0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0,
0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0
};
static Texture16 hstripe = {
0xffff, 0xffff, 0xffff, 0xffff,
0x0000, 0x0000, 0x0000, 0x0000,
0xffff, 0xffff, 0xffff, 0xffff,
0x0000, 0x0000, 0x0000, 0x0000,
};
artdeco()
{
texture16(&display, Rect(display.rect.origin.x, display.rect.origin.y,
display.rect.corner.x, Drect.origin.y), &vstripe, F_XOR);
texture16(&display, Rect(display.rect.origin.x, Drect.origin.y,
Drect.origin.x, Drect.corner.y), &hstripe, F_XOR);
texture16(&display, Rect(Drect.corner.x, Drect.origin.y,
display.rect.corner.x, Drect.corner.y), &hstripe, F_XOR);
texture16(&display, Rect(display.rect.origin.x, Drect.corner.y,
display.rect.corner.x, display.rect.corner.y), &vstripe, F_XOR);
}
/* graphics support; for now there are some unimplemented operations */
#define MAXPOINTS 60
#define PATH_NONE -1
#define PATH_SEGMENT 0
#define PATH_SPLINE 1
#define PATH_CIRCLE 2
#define PATH_ELLIPSE 3
int path_type = PATH_NONE;
int pen_size = 1;
struct {
Point c_center;
Point c_start;
Point c_finish;
} path_circle;
struct {
Point e_center;
Point e_start;
Point e_finish;
short e_xradius;
short e_yradius;
} path_ellipse;
Point path_pts[MAXPOINTS+2];
int path_len;
define_path(c)
{
register int i, n;
register Point *pp;
path_type = (c==DMD_SEGMENT) ? PATH_SEGMENT : PATH_SPLINE;
n = inshort();
path_len = n;
if (path_len > MAXPOINTS) {
path_len = MAXPOINTS;
for (i = path_len; i < n; i++)
(void)inpoint();
}
pp = &path_pts[1];
for (i = 0; i < path_len; i++)
*pp++ = inpoint();
}
define_circle()
{
path_circle.c_center = inpoint();
path_circle.c_start = inpoint();
path_circle.c_finish = inpoint();
path_type = PATH_CIRCLE;
}
define_ellipse()
{
path_ellipse.e_center = inpoint();
path_ellipse.e_start = inpoint();
path_ellipse.e_finish = inpoint();
path_ellipse.e_xradius = inshort();
path_ellipse.e_yradius = inshort();
path_type = PATH_ELLIPSE;
}
draw_path()
{
int rop;
rop = inchar(); /* ignore for now */
switch (path_type) {
case PATH_SEGMENT:
draw_segment(F_OR);
break;
case PATH_SPLINE:
draw_spline(F_OR);
break;
case PATH_CIRCLE:
draw_circle(F_OR);
break;
case PATH_ELLIPSE:
draw_ellipse(F_OR);
break;
}
}
fill_path()
{
int rop;
rop = inchar(); /* ignore for now */
}
set_pen()
{
int i = inchar();
if (i < 1)
i = 1;
pen_size = i;
}
/* draw a spline path */
draw_spline(f)
int f;
{
register Point *pp = path_pts;
register long w, t1, t2, t3, scale=1000;
register int i, j, steps=10;
int n = path_len + 1;
Point p, q;
pp[0] = pp[1];
pp[n] = pp[n-1];
p = pp[0];
for (i = 0; i < n-1; i++) {
for (j = 0; j < steps; j++) {
w = scale * j / steps;
t1 = w * w / (2 * scale);
w = w - scale/2;
t2 = 3*scale/4 - w * w / scale;
w = w - scale/2;
t3 = w * w / (2*scale);
q.x = (t1*pp[i+2].x + t2*pp[i+1].x +
t3*pp[i].x + scale/2) / scale;
q.y = (t1*pp[i+2].y + t2*pp[i+1].y +
t3*pp[i].y + scale/2) / scale;
line_btw(p, q, f);
p = q;
}
}
}
/* draw a segment path */
draw_segment(f)
int f;
{
register Point *pp;
register int i;
pp = &path_pts[1];
if (path_len == 1) {
if (pen_size > 1)
disc(&display, pp[0], pen_size, f);
else
point(&display, pp[0], f);
} else {
for (i = 1; i < path_len; i++) {
line_btw(pp[0], pp[1], f);
pp++;
}
}
}
draw_circle(f)
int f;
{
/* ignore pen size for now */
if (path_circle.c_center.x == path_circle.c_finish.x &&
path_circle.c_center.y == path_circle.c_finish.y) {
circle(&display, path_circle.c_center, path_circle.c_start.x, f);
} else {
arc(&display, path_circle.c_center, path_circle.c_start,
path_circle.c_finish, f);
}
}
draw_ellipse(f)
int f;
{
/* ignore pen size for now */
if (path_ellipse.e_center.x == path_ellipse.e_finish.x &&
path_ellipse.e_center.y == path_ellipse.e_finish.y) {
ellipse(&display, path_ellipse.e_center, path_ellipse.e_xradius,
path_ellipse.e_yradius, f);
} else {
elarc(&display, path_ellipse.e_center, path_ellipse.e_xradius,
path_ellipse.e_yradius, path_ellipse.e_start,
path_ellipse.e_finish, f);
}
}
/* Draw a line on the screen. */
line_btw(p0, p1, rop)
Point p0, p1;
{
register int i;
register int incx;
if (abs(p1.y-p0.y) > abs(p1.x-p0.x)) {
incx = 1;
p0.x -= pen_size/2;
p1.x -= pen_size/2;
} else {
incx = 0;
p0.y -= pen_size/2;
p1.y -= pen_size/2;
}
for (i = 0; i < pen_size; i++) {
segment(&display, p0, p1, rop);
if (incx) {
p0.x++; p1.x++;
} else {
p0.y++; p1.y++;
}
}
}